package com.mz.mattress.client.task;

import com.mz.mattress.api.common.StepBean;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 步骤任务执行器
 */
@Slf4j
public abstract class AbstractStepTaskHandler<T extends TaskStepBean> implements TaskHandler<T> {

    public void handler(T data) {
        Method[] methodArr = this.getClass().getDeclaredMethods();
        if (methodArr.length < 1) {
            log.error("获取不到类方法,丢弃任务");
            return;
        }

        List<StepBean> stepBeanList = new ArrayList<>();
        for (Method method : methodArr) {
            TaskStep step = method.getAnnotation(TaskStep.class);
            if (step == null) {
                continue;
            }

            StepBean stepBean = new StepBean();
            stepBean.setNum(step.value());
            stepBean.setMethod(method);
            stepBean.setDelayTime(step.delayTime());
            stepBeanList.add(stepBean);
        }

        data.setStepList(stepBeanList);

        while (!data.canFinish()) {
            StepBean stepBean = data.queryCurrStep();
//            StepBean stepBean = new StepBean();
            if (stepBean == null) {
                data.nextStep();
                continue;
            }

            doHandler(stepBean.getMethod(), data);

            if (data.isFinishFlag()) {
                break;
            }

            // 等待回调任务
//            if (stepBean.isNeedWaiting()) {
//                CommTaskBean<T> task = new CommTaskBean<T>(this, data);
//                WaitingTaskTimer.waitingTask(data.getMobileImsi(), task);
//                return;
//            }

            long delayTime = stepBean.getDelayTime();
            if (delayTime > 0) {
                log.info("任务{}延迟{}毫秒执行", data.getTokenId(), delayTime);
                CommTaskBean<T> task = new CommTaskBean<T>(this, data);
//                TaskTimingTimer.delayTask(task, delayTime);
                return;
            }
        }

        finishTask(data);
    }

    public abstract void finishTask(T data);

    private void doHandler(Method method, T data) {
        try {
            method.invoke(this, data);
            data.nextStep();
            return;
        } catch (IllegalAccessException e) {
            log.error("任务{}执行方法{}失败", new Object[]{data.getTokenId(), method.getName(), e});
        } catch (IllegalArgumentException e) {
            log.error("任务{}执行方法{}失败", new Object[]{data.getTokenId(), method.getName(), e});
        } catch (InvocationTargetException e) {
            log.error("任务{}执行方法{}失败", new Object[]{data.getTokenId(), method.getName(), e});
        } catch (Exception e) {
            log.error("任务{}执行方法{}失败", new Object[]{data.getTokenId(), method.getName(), e});
        }

        log.warn("当前任务[{}]执行报错，结束任务", data.getTokenId());
        data.setFinishFlag(true);
    }

}
